package com.dog.modules.system.service.impl;

import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.dog.framework.core.constant.SecurityConstants;
import com.dog.framework.core.exception.ServiceException;
import com.dog.framework.core.model.JwtUser;
import com.dog.framework.core.utils.TreeUtils;
import com.dog.framework.mybatis.service.impl.BaseServiceImpl;
import com.dog.framework.redis.service.RedisService;
import com.dog.framework.web.util.SecurityUserUtils;
import com.dog.modules.system.api.vo.SysMenuVO;
import com.dog.modules.system.convert.SysMenuConvert;
import com.dog.modules.system.domain.SysMenu;
import com.dog.modules.system.domain.SysRole;
import com.dog.modules.system.domain.SysRoleMenu;
import com.dog.modules.system.mapper.SysMenuMapper;
import com.dog.modules.system.service.SysMenuService;
import com.dog.modules.system.service.SysRoleMenuService;
import com.dog.modules.system.service.SysRoleService;
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Service;

import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import java.util.stream.Collectors;

/**
 * @author liuxk
 * @description 针对表【sys_menu(菜单管理)】的数据库操作Service实现
 * @createDate 2024-01-30 14:47:29
 */
@Service
@AllArgsConstructor
public class SysMenuServiceImpl extends BaseServiceImpl<SysMenuMapper, SysMenu> implements SysMenuService {

    private final SysRoleMenuService sysRoleMenuService;

    private final SysRoleService sysRoleService;

    private final RedisService redisService;

    @Override
    public void save(SysMenuVO vo) {
        SysMenu entity = SysMenuConvert.INSTANCE.convert(vo);
        // 保存菜单
        baseMapper.insert(entity);
    }

    @Override
    public void update(SysMenuVO vo) {
        SysMenu entity = SysMenuConvert.INSTANCE.convert(vo);

        // 上级菜单不能为自己
        if (entity.getId().equals(entity.getPid())) {
            throw new ServiceException("上级菜单不能为自己");
        }

        // 更新菜单
        updateById(entity);
    }

    @Override
    public void delete(Long id) {
        // 删除菜单
        removeById(id);

        // 删除角色菜单关系
        sysRoleMenuService.deleteByMenuId(id);
    }

    @Override
    public List<SysMenuVO> getMenuList(Integer type) {
        List<SysMenu> menuList = baseMapper.getMenuList(type);
        return TreeUtils.build(SysMenuConvert.INSTANCE.convertList(menuList));
    }

    @Override
    public List<SysMenuVO> getUserMenuList(JwtUser user, Integer type) {
        List<SysMenu> menuList;

        // 系统管理员，拥有最高权限
        if (SecurityUserUtils.isAdmin(SecurityUserUtils.getUserId())) {
            menuList = baseMapper.getMenuList(type);
        } else {
            menuList = baseMapper.getUserMenuList(user.getUserId(), type);
        }

        return TreeUtils.build(SysMenuConvert.INSTANCE.convertList(menuList));
    }

    @Override
    public Long getSubMenuCount(Long pid) {
        return count(new LambdaQueryWrapper<SysMenu>().eq(SysMenu::getPid, pid));
    }

    @Override
    public Set<String> getUserAuthority(JwtUser user) {
        // 系统管理员，拥有最高权限
        List<String> authorityList;
        if (SecurityUserUtils.isAdmin(SecurityUserUtils.getUserId())) {
            authorityList = baseMapper.getAuthorityList();
        } else {
            authorityList = baseMapper.getUserAuthorityList(user.getUserId());
        }

        // 用户权限列表
        Set<String> permsSet = new HashSet<>();
        for (String authority : authorityList) {
            if (StrUtil.isBlank(authority)) {
                continue;
            }
            permsSet.addAll(Arrays.asList(authority.trim().split(",")));
        }

        return permsSet;
    }


    @Override
    public Map<String,List<String>> initResourceRolesMap() {
        Map<String,List<String>> resourceRoleMap = new TreeMap<>();
        List<SysMenu> sysMenuList = this.list();
        List<SysRole> sysRoleList = sysRoleService.list();
        List<SysRoleMenu> sysRoleMenuList = sysRoleMenuService.list();
        for (SysMenu sysMenu : sysMenuList) {
            Set<Long> roleIds = sysRoleMenuList.stream().filter(item -> item.getMenuId().equals(sysMenu.getId())).map(SysRoleMenu::getRoleId).collect(Collectors.toSet());
            List<String> roleCodeList = sysRoleList.stream().filter(item -> roleIds.contains(item.getId())).map(item -> item.getRoleCode()).distinct().collect(Collectors.toList());
            resourceRoleMap.put(sysMenu.getUrl(),roleCodeList);
        }
        redisService.delete(SecurityConstants.RESOURCE_ROLES_MAP_KEY);
        redisService.setCacheMap(SecurityConstants.RESOURCE_ROLES_MAP_KEY, resourceRoleMap);
        return resourceRoleMap;

    }

}




